package com.powernode.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.constant.ManagerConstants;
import com.powernode.domain.SysRole;
import com.powernode.domain.SysRoleMenu;
import com.powernode.dto.SysRoleUpdateDto;
import com.powernode.mapper.SysRoleMapper;
import com.powernode.mapper.SysRoleMenuMapper;
import com.powernode.service.SysRoleMenuService;
import com.powernode.service.SysRoleService;
import com.powernode.util.AuthUtil;
import com.powernode.vo.SysRoleInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
@CacheConfig(cacheNames = "com.powernode.service.impl.SysRoleServiceImpl")
@Slf4j
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService{


    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    /**
     * 查询所有角色信息[全量查询]
     *  一般全量查询是需要将查询出来的数据放到缓存中去的
     *
     *  注解式缓存使用步骤
     *      第一步:在启动类上开启注解式缓存 @EnableCaching
     *      第二步:在服务类上使用@CacheConfig(cacheNames="全限定类名")
     *      第三步:在方法上指定key
     * @return
     */
    @Override
    @Cacheable(key = ManagerConstants.SYS_ALL_ROLE_LIST_KEY)
    public List<SysRole> queryRoleList() {
        return this.list(
                new LambdaQueryWrapper<SysRole>()
                .orderByDesc(SysRole::getCreateTime)
        );
    }

    /**
     * 根据角色id查询角色信息
     * @param rid
     * @return
     */
    @Override
    public SysRoleInfoVo queryRoleInfoByrid(Long rid) {
        SysRole sysRole = sysRoleMapper.selectById(rid);

        SysRoleInfoVo sysRoleInfoVo = new SysRoleInfoVo();

        List<SysRoleMenu> sysRoleMenus = sysRoleMenuMapper.selectList(
                new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, rid)
        );

        sysRoleInfoVo.setRoleName(sysRole.getRoleName());
        sysRoleInfoVo.setRemark(sysRole.getRemark());
        //sysRoleMenus.forEach(sysRoleMenu -> {
        //    sysRoleInfoVo.getMenuIdList().add(sysRoleMenu.getMenuId());
        //});
        //sysRoleInfoVo.setMenuIdList(sysRoleMenus);

        List<Long> menusIdList = new ArrayList<>();

        if (sysRoleMenus != null && sysRoleMenus.size() > 0) {
            sysRoleMenus.forEach(sysRoleMenu -> {
                menusIdList.add(sysRoleMenu.getMenuId());
            });
        }
        sysRoleInfoVo.setMenuIdList(menusIdList);
        return sysRoleInfoVo;

    }

    /**
     * 新增角色信息
     * @param sysRole
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer saveRole(SysRole sysRole) {
        // 设置创建时间和创建人
        sysRole.setCreateTime(new Date());
        Long loginUserId = AuthUtil.getLoginUserId();
        sysRole.setCreateUserId(loginUserId);

        // 新增角色信息
        int insertRole = sysRoleMapper.insert(sysRole);



        log.info("@新增角色信息RoleId:{}",sysRole.getRoleId());

        // 新增角色和菜单的关系
        // 封装一个角色菜单关系list,批量插入
        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();

        List<Long> menuIdList = sysRole.getMenuIdList();
        if (menuIdList != null && menuIdList.size() > 0) {
            menuIdList.stream().forEach(menuId -> {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(sysRole.getRoleId());
                sysRoleMenu.setMenuId(menuId);
                sysRoleMenus.add(sysRoleMenu);
            });
        }
        boolean b = sysRoleMenuService.saveBatch(sysRoleMenus);


        return insertRole;
    }

    /**
     * 根据角色id删除角色信息,这里需要清除redis中保存的role信息
     *
     * @param roleIds
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = ManagerConstants.SYS_ALL_ROLE_LIST_KEY)
    public Integer removeRoleByIds(List<Long> roleIds) {
        if (roleIds == null || roleIds.size() < 1 ) {
            return 0;
        }
        // 删除角色信息
        int i = sysRoleMapper.deleteBatchIds(roleIds);

        // 删除角色和菜单关系
        sysRoleMenuMapper.delete(
                new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, roleIds)
        );
        return i;
    }

    /**
     * 修改角色信息
     * 这里需要清除redis中保存的role信息
     * @param sysRoleUpdateDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = ManagerConstants.SYS_ALL_ROLE_LIST_KEY)
    public Integer modifyRoleInfo(SysRoleUpdateDto sysRoleUpdateDto) {
        SysRole sysRole = new SysRole();

        BeanUtils.copyProperties(sysRoleUpdateDto, sysRole);

        // 修改角色信息
        int i = sysRoleMapper.updateById(sysRole);



        // 删除该角色所有的菜单关系
        sysRoleMenuMapper.delete(
                new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, sysRoleUpdateDto.getRoleId())
        );
        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();

        // 重新添加角色和菜单关系
        if (sysRoleUpdateDto.getMenuIdList() != null && sysRoleUpdateDto.getMenuIdList().size() > 0){
            sysRoleUpdateDto.getMenuIdList().stream().forEach(menuId -> {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(sysRoleUpdateDto.getRoleId());
                sysRoleMenu.setMenuId(menuId);
                sysRoleMenus.add(sysRoleMenu);
            });
            sysRoleMenuService.saveBatch(sysRoleMenus);
        }

        return i;
    }


}
